#ifndef __TCP_SERVER_H__
#define __TCP_SERVER_H__
#include<iostream>
#include<sys/socket.h>
#include<sys/types.h>
#include<unistd.h>
#include<string>
#include<cstdlib>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<cstring>
#include<signal.h>
#include<pthread.h>

#include"ThreadPool.hpp"
#define BACKLOG 5
class tcpServer {
private:
    int ser_port;
    //监听套接字
    int lsock;
    //创建线程池指针
    ThreadPool* tp;
public:
    tcpServer(int port = 8080) :ser_port(port), lsock(-1),tp(nullptr){       
    }
    void initServer() {
        //signal(SIGCHLD,SIG_IGN);
        lsock = socket(AF_INET, SOCK_STREAM, 0);
        if (lsock < 0) {
            std::cerr << "lsocket error" << std::endl;
            exit(2);
        }
        struct sockaddr_in local;
        local.sin_family = AF_INET;
        local.sin_port = htons(ser_port);
        local.sin_addr.s_addr = htonl(INADDR_ANY);
        

        if(bind(lsock,(struct sockaddr*)&local,sizeof(local)) < 0){
            std::cerr<<"bind error!"<<std::endl;
            exit(3);
        }
        //监听
        if(listen(lsock,BACKLOG)){
            std::cerr<<"bind error!"<<std::endl;
            exit(4);
        }
        
        tp = new ThreadPool();
        tp->ThreadInit();
    }

    static void service(int sock){
        char buffer[128];
        while(true){
            ssize_t s = recv(sock,buffer,sizeof(buffer)-1,0);
            if(s > 0){
                buffer[s] = 0;
                std::cout<<"Client #" <<buffer <<std::endl;

                send(sock,buffer,strlen(buffer),0);
            }
            else if(s == 0){
                std::cout<<"Client quit ..."<<std::endl;
                break;
            }
            else{
                std::cout<<"recv error"<<std::endl;
                break;
            }
        }
        close(sock);
    }
    
    static void* serviceRoutine(void* arg){
        pthread_detach(pthread_self());
        std::cout << "create a new thread for IO" << std::endl;
        int* p = (int*)arg;
        int sock = *p;
        service(sock);
        delete p;
    }
    void start(){
        std::cout<<"tcpServer start"<<std::endl;
        struct sockaddr_in end_ponint; 
        while(true){
            socklen_t len = sizeof(end_ponint);
            int sock = accept(lsock,(struct sockaddr*)&end_ponint,&len); 
            if(sock < 0){
                std::cerr << "accept error !"<<std::endl;
                continue;
            }
            std::string Cli_info = inet_ntoa(end_ponint.sin_addr);
            Cli_info += ":";
            Cli_info += std::to_string(ntohs(end_ponint.sin_port));

            std::cout<<"get a new link ["<<Cli_info<<"]"<<std::endl;
         //   pid_t pid =fork();
         //   if(pid ==0){
         //       //child
         //       close(lsock);
         //       service(sock);
         //       exit(0);
         //   }
         //   close(sock);
         //   int* p = new int(sock);
         //   pthread_t tid;
         //   pthread_create(&tid,nullptr, serviceRoutine ,(void*)p);
            Task* t = new Task(sock);
            tp->Put(*t);
        }
    }
    ~tcpServer() {
        close(lsock);
    }
};
#endif
